package com.common.base.utils

import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.*
import android.media.ExifInterface
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.renderscript.Allocation
import android.renderscript.Element
import android.renderscript.RenderScript
import android.renderscript.ScriptIntrinsicBlur
import android.text.format.DateUtils
import android.view.View
import androidx.annotation.RequiresApi
import androidx.core.widget.NestedScrollView
import com.common.base.R
import com.common.base.utils.AppUtils.getColor
import java.io.*
import java.text.SimpleDateFormat
import java.util.*


/**
 * 图片处理工具类
 */
object BitmapUtils {

    //图片保存位置
    val fileImage =
        File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath + "/mvp-ma")

    //相机图片保存位置
    val fileImageCamera =
        File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath + "/Camera")

    /**
     * Bitmap保存为文件
     */
    fun saveBitmapToFile(bitmap: Bitmap, path: String): File? {
        var out: FileOutputStream? = null
        try {
            out = FileOutputStream(path)
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out) // bmp is your Bitmap instance
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        } finally {
            try {
                out?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return File(path)
    }

    /**
     * Bitmap 转 bytes
     */
    fun bitmapToBytes(bitmap: Bitmap?): ByteArray? {
        var byteArrayOutputStream: ByteArrayOutputStream? = null
        if (bitmap != null && !bitmap.isRecycled) {
            try {
                byteArrayOutputStream = ByteArrayOutputStream()
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream)
                if (byteArrayOutputStream.toByteArray() == null) {
                    LogUtils.e("BitmapUtils", "bitmap2Bytes byteArrayOutputStream toByteArray=null")
                }
                return byteArrayOutputStream.toByteArray()
            } catch (e: Exception) {
                LogUtils.e("BitmapUtils", e.toString())
            } finally {
                try {
                    byteArrayOutputStream?.close()
                } catch (var14: IOException) {
                }
            }
            return null
        } else {
            LogUtils.e("BitmapUtils", "bitmap2Bytes bitmap == null or bitmap.isRecycled()")
            return null
        }
    }

    /**
     * 在保证质量的情况下尽可能压缩，不保证压缩到指定字节
     */
    fun compressBitmap(data: ByteArray?, byteCount: Int): ByteArray? {
        var isFinish = false
        if (data != null && data.size > byteCount) {
            val outputStream = ByteArrayOutputStream()
            val tmpBitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
            var times = 1
            var percentage: Double
            while (!isFinish && times <= 10) {
                percentage = Math.pow(0.8, times.toDouble())
                val compressData = (100.0 * percentage).toInt()
                tmpBitmap.compress(Bitmap.CompressFormat.JPEG, compressData, outputStream)
                if (outputStream.size() < byteCount) {
                    isFinish = true
                } else {
                    outputStream.reset()
                    ++times
                }
            }
            val outputStreamByte = outputStream.toByteArray()
            if (!tmpBitmap.isRecycled) {
                tmpBitmap.recycle()
            }
            if (outputStreamByte.size > byteCount) {
                LogUtils.e(
                    "BitmapUtils",
                    "compressBitmap cannot compress to " + byteCount + ", after compress size=" + outputStreamByte.size
                )
            }
            return outputStreamByte
        }
        return data
    }


    private const val BITMAP_SCALE: Float = 0.4f
    private const val BLUR_RADIUS: Int = 7

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    @JvmStatic
    fun blur(
        context: Context,
        bitmap: Bitmap,
        scale: Float = BITMAP_SCALE,
        radius: Int = BLUR_RADIUS
    ): Bitmap {
        //先对图片进行压缩然后再blur
        val inputBitmap: Bitmap = Bitmap.createScaledBitmap(
            bitmap, Math.round(bitmap.width * scale),
            Math.round(bitmap.height * scale), false
        )
        //创建空的Bitmap用于输出
        val outputBitmap: Bitmap = Bitmap.createBitmap(inputBitmap)
        //①、初始化Renderscript
        val rs: RenderScript = RenderScript.create(context)
        //②、Create an Intrinsic Blur Script using the Renderscript
        val theIntrinsic: ScriptIntrinsicBlur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
        //③、native层分配内存空间
        val tmpIn: Allocation = Allocation.createFromBitmap(rs, inputBitmap)
        val tmpOut: Allocation = Allocation.createFromBitmap(rs, outputBitmap)
        //④、设置blur的半径然后进行blur
        theIntrinsic.setRadius(radius.toFloat())
        theIntrinsic.setInput(tmpIn)
        theIntrinsic.forEach(tmpOut)
        //⑤、拷贝blur后的数据到java缓冲区中
        tmpOut.copyTo(outputBitmap)
        //⑥、销毁Renderscript
        rs.destroy()
        bitmap.recycle()
        return outputBitmap
    }

    fun getBmpSize(bmpPath: String): IntArray {
        val result = IntArray(2)

        try {
            val options = BitmapFactory.Options()
            options.inJustDecodeBounds = true
            BitmapFactory.decodeFile(bmpPath, options)
            val width = options.outWidth
            val height = options.outHeight

            result[0] = width
            result[1] = height

            val exifInterface = ExifInterface(bmpPath)
            val orientation = exifInterface.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL
            )
            when (orientation) {
                ExifInterface.ORIENTATION_ROTATE_90, ExifInterface.ORIENTATION_ROTATE_270 -> {
                    result[0] = height
                    result[1] = width
                }
                else -> {
                    result[0] = width
                    result[1] = height
                }
            }

        } catch (e: java.lang.Exception) {

        }

        return result
    }

    /**
     * 转换图片成圆形
     * @param bitmap
     * 传入Bitmap对象
     * @return
     */
    fun toRoundBitmap(bitmap: Bitmap): Bitmap? {
        var width = bitmap.width
        var height = bitmap.height
        val roundPx: Float
        val left: Float
        val top: Float
        val right: Float
        val bottom: Float
        val dst_left: Float
        val dst_top: Float
        val dst_right: Float
        val dst_bottom: Float
        if (width <= height) {
            roundPx = (width / 2).toFloat()
            left = 0f
            top = 0f
            right = width.toFloat()
            bottom = width.toFloat()
            height = width
            dst_left = 0f
            dst_top = 0f
            dst_right = width.toFloat()
            dst_bottom = width.toFloat()
        } else {
            roundPx = (height / 2).toFloat()
            val clip = ((width - height) / 2).toFloat()
            left = clip
            right = width - clip
            top = 0f
            bottom = height.toFloat()
            width = height
            dst_left = 0f
            dst_top = 0f
            dst_right = height.toFloat()
            dst_bottom = height.toFloat()
        }
        val output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(output)
        val color = -0xbdbdbe
        val paint = Paint()
        val src = Rect(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
        val dst = Rect(
            dst_left.toInt(), dst_top.toInt(), dst_right.toInt(),
            dst_bottom.toInt()
        )
        paint.isAntiAlias = true // 设置画笔无锯齿
        canvas.drawARGB(0, 0, 0, 0) // 填充整个Canvas
        paint.color = color

        // 以下有两种方法画圆,drawRounRect和drawCircle
        // canvas.drawRoundRect(rectF, roundPx, roundPx, paint);// 画圆角矩形，第一个参数为图形显示区域，第二个参数和第三个参数分别是水平圆角半径和垂直圆角半径。
        canvas.drawCircle(roundPx, roundPx, roundPx, paint)
        paint.xfermode =
            PorterDuffXfermode(PorterDuff.Mode.SRC_IN) // 设置两张图片相交时的模式,参考http://trylovecatch.iteye.com/blog/1189452
        canvas.drawBitmap(bitmap, src, dst, paint) //以Mode.SRC_IN模式合并bitmap和已经draw了的Circle
        return output
    }

    fun imageScale(bitmap: Bitmap?, dstWidth: Int, dstHeight: Int): Bitmap? {
        if (bitmap == null) {
            return null
        }
        val srcWidth: Int = bitmap.width
        val srcHeight: Int = bitmap.height

        val scaleWidth: Float = (dstWidth * 1.0f) / srcWidth
        val scaleHeight: Float = (dstHeight * 1.0f) / srcHeight

        val matrix = Matrix()
        matrix.postScale(scaleWidth, scaleHeight)
        return Bitmap.createBitmap(bitmap, 0, 0, srcWidth, srcHeight, matrix, true)
    }


    fun drawText2Bitmap(
        text: String,
        textSize: Float,
        imgResourceId: Int,
        diffX: Int = 0,
        diffY: Int = 0,
        isBold: Boolean = false
    ): Bitmap? {
        try {
            val resources = AppUtils.getContext().resources
            var bitmap = BitmapFactory.decodeResource(resources, imgResourceId)

            var bitmapConfig: Bitmap.Config? = bitmap.config
            if (bitmapConfig == null) {
                bitmapConfig = Bitmap.Config.ARGB_8888
            }
            bitmap = bitmap.copy(bitmapConfig, true)

            val canvas = Canvas(bitmap)
            val paint = Paint(Paint.ANTI_ALIAS_FLAG)
            paint.color = Color.WHITE
            paint.textSize = textSize

            if (isBold) {
                val font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD)
                paint.typeface = font
            }

//            paint.setShadowLayer(1f, 0f, 1f, Color.DKGRAY)
            val bounds = Rect()
            paint.getTextBounds(text, 0, text.length, bounds)
            val x: Int = (bitmap.width - bounds.width()) / 2 + diffX
            val y: Int = (bitmap.height + bounds.height()) / 2 + diffY

            canvas.drawText(text, x.toFloat(), y.toFloat(), paint)
            return bitmap
        } catch (e: Exception) {
            return null
        }
    }

    fun getBitmapByResId(imgResourceId: Int): Bitmap? {
        val resources = AppUtils.getContext().resources
        return BitmapFactory.decodeResource(resources, imgResourceId)
    }

    //TODO OPT
    fun getBadgeImageByLevel(level: Int): Int {
        return getResIdByName("icon_lv%d".format(level))
    }

    fun getBadgeImageByLevelV2(level: Int): Int {
        return getResIdByName("icon_v2_lv%d".format(level))
    }

    private fun getResIdByName(name: String): Int {
        val ctx = AppUtils.getContext()
        val resId: Int = ctx.resources.getIdentifier(name, "drawable", ctx.packageName)
        return resId
    }

    /**
     * 读取图片的旋转的角度
     * @param path
     * 图片绝对路径
     * @return 图片的旋转角度
     */
    private fun getBitmapDegree(path: String): Int {
        var degree = 0
        try {
            // 从指定路径下读取图片，并获取其EXIF信息
            val exifInterface = ExifInterface(path)
            // 获取图片的旋转信息
            val orientation = exifInterface.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL
            )
            when (orientation) {
                ExifInterface.ORIENTATION_ROTATE_90 -> degree = 90
                ExifInterface.ORIENTATION_ROTATE_180 -> degree = 180
                ExifInterface.ORIENTATION_ROTATE_270 -> degree = 270
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return degree
    }

    /**
     * 将图片按照某个角度进行旋转
     * @param bm
     * 需要旋转的图片
     * @param degree
     * 旋转角度
     * @return 旋转后的图片
     */
    fun rotateBitmapByDegree(bm: Bitmap, degree: Int): Bitmap {
        var returnBm: Bitmap? = null
        // 根据旋转角度，生成旋转矩阵
        val matrix = Matrix()
        matrix.postRotate(degree.toFloat())
        try {
            // 将原始图片按照旋转矩阵进行旋转，并得到新的图片
            returnBm = Bitmap.createBitmap(bm, 0, 0, bm.width, bm.height, matrix, true)
        } catch (e: OutOfMemoryError) {
            e.printStackTrace()
        }
        if (returnBm == null) {
            returnBm = bm
        }
        if (bm != returnBm) {
            bm.recycle()
        }
        return returnBm
    }

    /**
     * 根据view的宽度，动态缩放bitmap尺寸
     *
     * @param width
     * view的宽度
     */
    fun getScaledBitmap(filePath: String, width: Int): Bitmap? {
        if (filePath.isEmpty()) {
            return null
        }
        val options = BitmapFactory.Options()
        try {
            options.inJustDecodeBounds = true
            BitmapFactory.decodeFile(filePath, options)
            val sampleSize = if (options.outWidth > width)
                options.outWidth / width + 1
            else
                1
            options.inJustDecodeBounds = false
            options.inSampleSize = sampleSize
        } catch (e: Exception) {
            e.printStackTrace()
        }
        val bitmap = BitmapFactory.decodeFile(filePath, options)
        val degree = getBitmapDegree(filePath)
        return rotateBitmapByDegree(bitmap, degree)
    }


    fun loadBitmapFromView(v: View, width: Int, height: Int): Bitmap? {
//        Logger.i("w=" + width + "h=" + height);
        val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val c = Canvas(bmp)
        /** 如果不设置canvas画布为白色，则生成透明  */
        c.drawColor(Color.WHITE)
        v.layout(0, 0, width, height)
        v.draw(c)
        return bmp
    }


    fun loadBitmapFromViewTr(v: View, width: Int, height: Int): Bitmap? {
//        Logger.i("w=" + width + "h=" + height);
        val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val c = Canvas(bmp)
        /** 如果不设置canvas画布为白色，则生成透明  */
        c.drawColor(Color.TRANSPARENT)
        v.layout(0, 0, width, height)
        v.draw(c)
        return bmp
    }

    /**
     * 保存图片到图库
     *
     * @param context
     * @param bmp
     */
    fun saveImageToGallery(context: Context, bmp: Bitmap?) {

        bmp?.let {

            // 首先保存图片
//        File appDir = App.fileImage;
//        File appDir = App.fileImageCamera;
            var appDir: File? = null
            val brand = Build.BRAND
            appDir = if (brand.equals("Huawei", ignoreCase = true)) {
                fileImageCamera
            } else {
                fileImage
            }
            if (!appDir.exists()) {
                appDir.mkdir()
            }
            var fileName = "" // 不用JPG,解决图片黑四角
            var file: File?
            if (brand.equals("Huawei", ignoreCase = true)) {
                fileName = System.currentTimeMillis().toString() + ".jpg" // 不用JPG,解决图片黑四角
                file = File(appDir, fileName)
                try {
                    val fos = FileOutputStream(file)
                    it.compress(Bitmap.CompressFormat.JPEG, 100, fos)
                    fos.flush()
                    fos.close()
                    ToastUtils.showToast("保存成功!")
                } catch (e: FileNotFoundException) {
                    ToastUtils.showToast("保存失败!")
                    e.printStackTrace()
                } catch (e: IOException) {
                    ToastUtils.showToast("保存失败!")
                    e.printStackTrace()
                }

//            // 其次把文件插入到系统图库
//            try {
//                MediaStore.Images.Media.insertImage(context.getContentResolver(),
//                        file.getAbsolutePath(), fileName, null);
//                PToastUtils.t(context, "保存成功");
//            } catch (FileNotFoundException e) {
//                PToastUtils.t(context, "保存失败");
//                e.printStackTrace();
//            }
            } else {
                fileName = System.currentTimeMillis().toString() + ".png" // 不用JPG,解决图片黑四角
                file = File(appDir, fileName)
                try {
                    val fos = FileOutputStream(file)
                    it.compress(Bitmap.CompressFormat.PNG, 100, fos)
                    fos.flush()
                    fos.close()
                } catch (e: FileNotFoundException) {
                    ToastUtils.showToast("保存失败!")
                    e.printStackTrace()
                } catch (e: IOException) {
                    ToastUtils.showToast("保存失败!")
                    e.printStackTrace()
                }

                // 其次把文件插入到系统图库
                try {
                    MediaStore.Images.Media.insertImage(
                        context.contentResolver,
                        file.absolutePath, fileName, null
                    )
                    ToastUtils.showToast("保存成功!")
                    file.delete()
                } catch (e: FileNotFoundException) {
                    ToastUtils.showToast("保存失败!")
                    e.printStackTrace()
                }
            }

            // 通知图库更新
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                MediaScannerConnection.scanFile(
                    context, arrayOf<String>(file.absolutePath), null
                ) { path, uri ->
                    val mediaScanIntent =
                        Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
                    mediaScanIntent.data = uri
                    AppUtils.getContext().sendBroadcast(mediaScanIntent)
                }
            } else {
                val relationDir = file.parent
                val file1 = File(relationDir)
                AppUtils.getContext().sendBroadcast(
                    Intent(
                        Intent.ACTION_MEDIA_MOUNTED,
                        Uri.fromFile(file1.absoluteFile)
                    )
                )
            }
//        // 最后通知图库更新
//        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
//                Uri.fromFile(new File(file.getPath()))));
        }
    }

    /**
     * ScrollView截屏-长图
     */
    fun shotScrollView(scrollView: NestedScrollView): Bitmap? {
        var h = 0
        for (i in 0 until scrollView.childCount) {
            h += scrollView.getChildAt(i).height
            scrollView.getChildAt(i).setBackgroundColor(getColor(R.color.color_F5F5F5))
        }
        val bitmap: Bitmap? = Bitmap.createBitmap(scrollView.width, h, Bitmap.Config.ARGB_8888)
        val canvas = bitmap?.let { Canvas(it) }
        if (canvas != null) {
            scrollView.draw(canvas)
        }
        return bitmap
    }

    @SuppressLint("NewApi")
    @RequiresApi(api = Build.VERSION_CODES.Q)
    fun saveImageToGallery4(context: Context, image: Bitmap?) {
        image?.let {
            val mImageTime = System.currentTimeMillis()
            val imageDate = SimpleDateFormat("yyyyMMdd-HHmmss").format(Date(mImageTime))
            val SCREENSHOT_FILE_NAME_TEMPLATE = "strategy_%s.png" //图片名称，以"winetalk"+时间戳命名
            val mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate)
            val values = ContentValues()
            values.put(
                MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES
                        + File.separator + "strategy"
            ) //Environment.DIRECTORY_SCREENSHOTS:截图,图库中显示的文件夹名。"dh"
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, mImageFileName)
            values.put(MediaStore.MediaColumns.MIME_TYPE, "image/png")
            values.put(MediaStore.MediaColumns.DATE_ADDED, mImageTime / 1000)
            values.put(MediaStore.MediaColumns.DATE_MODIFIED, mImageTime / 1000)
            values.put(
                MediaStore.MediaColumns.DATE_EXPIRES,
                (mImageTime + DateUtils.DAY_IN_MILLIS) / 1000
            )
            values.put(MediaStore.MediaColumns.IS_PENDING, 1)
            val resolver = context.contentResolver
            val uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
            try {
                // First, write the actual data for our screenshot
                resolver.openOutputStream(uri!!)?.use { out ->
                    if (!it.compress(Bitmap.CompressFormat.PNG, 100, out)) {
                        throw IOException("Failed to compress")
                    }
                }
                // Everything went well above, publish it!
                values.clear()
                values.put(MediaStore.MediaColumns.IS_PENDING, 0)
                values.putNull(MediaStore.MediaColumns.DATE_EXPIRES)
                resolver.update(uri, values, null, null)
                ToastUtils.showToast("保存成功!")
            } catch (e: FileNotFoundException) {
                resolver.delete(uri!!, null)
                ToastUtils.showToast("保存失败!")
                e.printStackTrace()
            } catch (e: IOException) {
                resolver.delete(uri!!, null)
                ToastUtils.showToast("保存失败!")
                e.printStackTrace()
            }
        }
    }
    fun saveImageToGallery(filePath: String, context: Context) {
        val contentResolver = context.contentResolver

        // 获取当前时间，作为图片的名称
        val fileName = "IMG_" + SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date()) + ".jpg"

        // 设置保存图片的元数据信息
        val values = ContentValues().apply {
            put(MediaStore.Images.Media.TITLE, fileName)
            put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
            put(MediaStore.Images.Media.DESCRIPTION, "Image saved by app")
            put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")
            put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
            put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
        }

        // 将图片元数据信息插入到 MediaStore 中
        val imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
        try {
            // 保存图片文件到相册
            val outputStream = contentResolver.openOutputStream(imageUri!!)
            val bitmap = BitmapFactory.decodeFile(filePath)
            if (outputStream != null) {
                bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream)
            }
            outputStream?.flush()
            outputStream?.close()
            ToastUtils.showToast("保存成功!")
        }catch (e: FileNotFoundException) {
            ToastUtils.showToast("保存失败!")
            e.printStackTrace()
        } catch (e: IOException) {
            ToastUtils.showToast("保存失败!")
            e.printStackTrace()
        }
    }

    /**
     * Bitmap 保存为临时 File 文件
     */
    fun saveTempBitmap(context: Context, bitmap: Bitmap?): File? {
        if (bitmap == null) return null
        // 获取缓存目录
        val cacheDir = context.cacheDir ?: return null
        // 创建临时文件
        val tempFile = File(cacheDir, "temp_image.jpg")
        if (tempFile.exists()) {
            // 如果文件已存在，则删除原来的文件
            tempFile.delete()
        }
        var fos: FileOutputStream? = null
        return try {
            fos = FileOutputStream(tempFile)
            // 压缩 Bitmap 并保存到临时文件
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
            fos.flush()
            tempFile
        } catch (e: IOException) {
            e.printStackTrace()
            null
        } finally {
            try {
                fos?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }
}